﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ProgramCat.FiddlerExtension.Core.JsonEditor
{
    /// <summary>
    /// 基于TreeView的 json显示组件
    /// </summary>
    public partial class JsonView : UserControl
    {
        /// <summary>
        /// 当项选择时事件
        /// </summary>
        /// <param name="value"></param>
        public delegate void delegateAfterSelect(JsonViewerTreeNode value);
        /// <summary>
        /// json原数据
        /// </summary>
        private string json = "";
        /// <summary>
        /// json原数据组装属性
        /// </summary>
        public string Json
        {
            get => json;
            set
            {
                if (json != value)
                {
                    //先到小写
                    json = value.Trim();
                    //刷新视图
                    RefreshView();
                }
            }
        }
        public delegateAfterSelect OnAfterSelect = null;


        public JsonView()
        {
            InitializeComponent();
        }



        private void RefreshView()
        {
            //通知TreeView 开始刷新
            jsonTreeView.BeginUpdate();
            try
            {
                //删除原数据节点
                Reset();
                if (!String.IsNullOrEmpty(json))
                { 
                    //解析json数据到 树结构
                    JsonObjectTree tree = JsonObjectTree.Parse(json);
                    //基于广度有限遍历
                    VisualizeJsonTree(tree);
                }
            }
            finally
            {

            }
            //通知TreeView 结束刷新
            jsonTreeView.EndUpdate();
        }
        private void Reset()
        {
            jsonTreeView.Nodes.Clear();
            
        }
        /// <summary>
        /// 折叠所有
        /// </summary>
        public void ExpandAll()
        {
            jsonTreeView.ExpandAll();
            jsonTreeView.Nodes?[0].EnsureVisible();
        }
        /// <summary>
        /// 展开所有
        /// </summary>
        public void CollapseAll()
        {
            jsonTreeView.CollapseAll();
        }
        private void VisualizeJsonTree(JsonObjectTree tree)
        {
            AddNode(jsonTreeView.Nodes, tree.Root);
            JsonViewerTreeNode node = GetRootNode();
            node.Expand();
            jsonTreeView.SelectedNode = node;
        }
        private void AddNode(TreeNodeCollection nodes, JsonObject jsonObject)
        {
            JsonViewerTreeNode newNode = new JsonViewerTreeNode(jsonObject);
            nodes.Add(newNode);
            newNode.Text = jsonObject.Text;
            newNode.Name = jsonObject.Id;
            newNode.Tag = jsonObject;
            newNode.ImageIndex = (int)jsonObject.JsonType;
            newNode.SelectedImageIndex = newNode.ImageIndex;

            foreach (JsonObject field in jsonObject.Fields)
            {
                AddNode(newNode.Nodes, field);
            }
        }
        private JsonViewerTreeNode GetRootNode()
        {
            if (jsonTreeView.Nodes.Count > 0)
                return (JsonViewerTreeNode)jsonTreeView.Nodes[0];
            return null;
        }
        private void jsonTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {

            JsonViewerTreeNode node = (JsonViewerTreeNode)e.Node;
            OnAfterSelect?.Invoke(node);
        }

    }

    public class JsonViewerTreeNode : TreeNode
    {
        JsonObject _jsonObject;
        List<ICustomTextProvider> _textVisualizers = new List<ICustomTextProvider>();
        List<IJsonVisualizer> _visualizers = new List<IJsonVisualizer>();
        private bool _init;
        private IJsonVisualizer _lastVisualizer;

        public string GetNodePath()
        {
            string path = "";
            JsonViewerTreeNode tempNode = this;

            while (tempNode?.Level != 0)
            {
                string name_ = tempNode.Name;
                JsonViewerTreeNode parent = (JsonViewerTreeNode)tempNode.Parent;
                if (parent.Level != 0)
                {
                    switch (parent.JsonObject.JsonType)
                    {
                        case JsonType.Object:
                            name_ = "." + name_;
                            break;
                        case JsonType.Array:
                            break;
                        case JsonType.Value:
                            name_ = "." + name_;
                            break;
                    }
                }
                path = name_ + path;
                tempNode = parent;
            }

            return path;
        }

        public JsonViewerTreeNode(JsonObject jsonObject)
        {
            _jsonObject = jsonObject;
        }

        public List<ICustomTextProvider> TextVisualizers
        {
            get
            {
                return _textVisualizers;
            }
        }

        public List<IJsonVisualizer> Visualizers
        {
            get
            {
                return _visualizers;
            }
        }

        public JsonObject JsonObject
        {
            get
            {
                return _jsonObject;
            }
        }

        internal bool Initialized
        {
            get
            {
                return _init;
            }
            set
            {
                _init = value;
            }
        }

        internal void RefreshText()
        {
            StringBuilder sb = new StringBuilder(_jsonObject.Text);
            foreach (ICustomTextProvider textVisualizer in _textVisualizers)
            {
                try
                {
                    string customText = textVisualizer.GetText(_jsonObject);
                    sb.Append(" (" + customText + ")");
                }
                catch
                {
                    //silently ignore
                }
            }
            string text = sb.ToString();
            if (text != this.Text)
                this.Text = text;
        }

        public IJsonVisualizer LastVisualizer
        {
            get
            {
                return _lastVisualizer;
            }
            set
            {
                _lastVisualizer = value;
            }
        }
    }



}
